package com.thirtydays.frame.util

import android.media.MediaPlayer
import android.media.MediaPlayer.*
import com.blankj.utilcode.util.ThreadUtils
import com.thirtydays.frame.base.BaseApp
import com.thirtydays.frame.util.ext.isNotNull
import com.thirtydays.frame.util.ext.isNull
import java.io.File
import java.io.IOException
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.ScheduledThreadPoolExecutor
import java.util.concurrent.TimeUnit


/**
 * @author 小垚
 * @创建时间： 2020/12/2
 * @描述：音频播放工具
 **/
object MediaPlayerUtil {

    private const val PLAY_STATE0 = 1 //文件
    private const val PLAY_STATE1 = 2 //raw
    private const val PLAY_STATE2 = 3 //assets
    private const val PLAY_STATE3 = 4 //网络

    //判断类型
    var PLAY_STATE = -1
    var isPlaying = false

    var targetFile: File? = null
    var rawId: Int? = null
    var mAssetsName = ""
    var mNetPath = ""
    private var isStop = false
    private var mMediaPlayer: MediaPlayer? = null
    private var functionManage = mutableListOf<MediaPlayFunctionListener>()
    private var playInfoManage = mutableListOf<MediaPlayInfoListener>()

    //多久获取一次进度 默认1秒
    private var sleep = 1L

    /**
     * 设置文件路径
     * @param file 需要播放文件的路径
     */
    fun setFilePlay(file: File) {
        targetFile = file
        PLAY_STATE = PLAY_STATE0
    }

    /**
     * 设置Raw播放
     * @param rawId R.raw.music3
     */
    fun setRawPlay(rawId: Int) {
        this.rawId = rawId
        PLAY_STATE = PLAY_STATE1
        stop()
    }

    /**
     * 设置Assets播放
     * 调用此方法必须在初始化时传入Context
     * @param assetsName assets文件名
     */
    fun setAssetsName(assetsName: String) {
        this.mAssetsName = assetsName
        PLAY_STATE = PLAY_STATE2
        stop()
    }

    /**
     * 设置网络资源播放
     * @param netPath 网络音乐地址
     */
    fun setNetPath(netPath: String) {
        this.mNetPath = netPath
        PLAY_STATE = PLAY_STATE3
        stop()
    }

    /**
     * 开始播放
     * @return true 开始播放， false 播放错误
     */
    fun start(): Boolean {
        if (mMediaPlayer.isNull()) {
            mMediaPlayer = if (PLAY_STATE == PLAY_STATE1) {
                create(BaseApp.appContent, rawId!!)
            } else {
                MediaPlayer()
            }
        }
        try {
            when (PLAY_STATE) {
                PLAY_STATE0 -> {
                    mMediaPlayer!!.setDataSource(targetFile!!.absolutePath)
                    mMediaPlayer!!.prepare()
                }
                PLAY_STATE1 -> {
                }
                PLAY_STATE2 -> {
                    val fileDescriptor = BaseApp.appContent.assets.openFd(mAssetsName)
                    mMediaPlayer!!.setDataSource(fileDescriptor.fileDescriptor, fileDescriptor.startOffset, fileDescriptor.length)
                    mMediaPlayer!!.prepare()
                }
                PLAY_STATE3 -> {
                    mMediaPlayer!!.setDataSource(mNetPath)
                    mMediaPlayer!!.prepareAsync()
                }
            }
            //播放完成自动停止
            mMediaPlayer!!.setOnCompletionListener { mediaPlayer ->
                if (playInfoManage.isNotEmpty()) {
                    playInfoManage.forEachIndexed { _, mediaPlayInfoListener ->
                        mediaPlayInfoListener.onCompletion(mediaPlayer)
                    }
                }
                stop()
            }
            //准备完毕 自动播放
            mMediaPlayer!!.setOnPreparedListener { mediaPlayer ->
                mediaPlayer.start()
                isStop = false
                getProgress()
                if (functionManage.isNotEmpty()) {
                    functionManage.forEachIndexed { _, mediaPlayFunctionListener ->
                        mediaPlayFunctionListener.prepared()
                        mediaPlayFunctionListener.start()
                    }
                }
            }
            //播放错误监听
            mMediaPlayer!!.setOnErrorListener { mp, what, extra ->
                if (playInfoManage.isNotEmpty()) {
                    playInfoManage.forEachIndexed { _, mediaPlayInfoListener ->
                        mediaPlayInfoListener.onError(mp, what, extra)
                    }
                }
                mFuture?.cancel(true)
                stop()
                false
            }
            //网络缓冲监听
            mMediaPlayer!!.setOnBufferingUpdateListener { mp, percent ->
                if (playInfoManage.isNotEmpty()) {
                    playInfoManage.forEachIndexed { _, mediaPlayInfoListener ->
                        mediaPlayInfoListener.onBufferingUpdate(mp, percent)
                    }
                }
            }
            //调整进度监听
            mMediaPlayer!!.setOnSeekCompleteListener { mp ->
                if (playInfoManage.isNotEmpty()) {
                    playInfoManage.forEachIndexed { _, mediaPlayInfoListener ->
                        mediaPlayInfoListener.onSeekComplete(mp)
                    }
                }
            }

        } catch (e: IOException) {
            e.printStackTrace()
            stop()
        }
        val result = mMediaPlayer != null
        isPlaying = result
        return result
    }

    private var mScheduledExecutorService = ScheduledThreadPoolExecutor(5)
    private var mFuture: ScheduledFuture<*>? = null
    private fun getProgress() {
        mMediaPlayer?.run {
            mFuture = mScheduledExecutorService.scheduleAtFixedRate({
                val p = currentPosition
                if (playInfoManage.isNotEmpty()) {
                    playInfoManage.forEachIndexed { _, mediaPlayInfoListener ->
                        ThreadUtils.runOnUiThread {
                            mediaPlayInfoListener.onSeekBarProgress(p)
                        }
                    }
                }
            }, 1, sleep, TimeUnit.SECONDS)
        }
    }

    /**
     *   停止播放
     */
    fun stop() {
        mMediaPlayer?.run {
            MediaPlayerUtil.isPlaying = false
            mFuture?.cancel(true)
            stop()
            reset()
            notifyFunctionManageReset()
            isStop = true
            null
        }
    }

    /**
     * resume调用 继续播放也调用此方法即可
     */
    fun resume() {
        mMediaPlayer?.run {
            this@MediaPlayerUtil.isPlaying = true
            getProgress()
            start()
            notifyFunctionManageContinuePlay()
        }
    }

    /**
     * 暂停
     */

    fun pause() {
        mMediaPlayer?.run {
            this@MediaPlayerUtil.isPlaying = false
            pause()
            mFuture?.cancel(true)
            notifyFunctionManagePause()
        }
    }

    /**
     * 暂停/播放
     */
    fun pausePlay() {
        if (this@MediaPlayerUtil.isPlaying) {
            pause()
        } else {
            if (isStop){
                start()
            }else{
                resume()
            }
        }
    }


    /**
     * 是否正在运行
     * @return true 正在运行，false停止运行
     */
    fun isRunning() = mMediaPlayer.isNotNull()

    /**
     * 播放文件的时长
     * @return 文件时长
     */
    fun getDuration() = if (mMediaPlayer.isNull()) 100 else mMediaPlayer!!.duration

    /**
     * 获取当前播放位置
     * @return 当前播放位置值
     */
    fun getCurrentPosition() = if (mMediaPlayer.isNull()) 0 else mMediaPlayer!!.currentPosition

    /**
     * 左右声道大小
     * @param leftVolume 左声道大小 0 - 1
     * @param rightVolume 右声道大小 0 - 1
     */
    fun setVolume(leftVolume: Float, rightVolume: Float) {
        mMediaPlayer?.run {
            setVolume(leftVolume, rightVolume)
        }
    }

    /**
     * 指定播放位置 毫秒
     * @param msec 要播放的值
     */
    fun seekTo(mesc: Int) {
        mMediaPlayer?.run {
            seekTo(mesc)
        }
    }

    /**
     * 是否循环播放
     * @param looping true 循环播放，false 不循环
     */
    fun setLooping(looping: Boolean) {
        mMediaPlayer?.run {
            isLooping = looping
        }
    }

    /**
     * 必须调用此方法 销毁，释放
     */
    fun destory() {
        stop()
    }

    /**
     * 多久获取一次进度 秒
     * @param sleep 默认1
     */
    fun setSleep(sleep: Long) {
        this.sleep = sleep
    }

    /**
     * 获取MediaPlayer对象
     * @return MediaPlayer
     */
    fun getMediaPlayer(): MediaPlayer? {
        return mMediaPlayer
    }


    /**
     * 通知暂停播放
     */
    private fun notifyFunctionManagePause() {
        if (functionManage.isNotEmpty()) {
            functionManage.forEachIndexed { _, mediaPlayFunctionListener ->
                mediaPlayFunctionListener.pause()
            }
        }
    }

    private fun notifyFunctionManageContinuePlay() {
        if (functionManage.isNotEmpty()) {
            functionManage.forEachIndexed { _, mediaPlayFunctionListener ->
                mediaPlayFunctionListener.continuePlay()
            }
        }
    }


    /**
     * 通知重置播放
     */
    private fun notifyFunctionManageReset() {
        if (functionManage.isNotEmpty()) {
            functionManage.forEachIndexed { _, mediaPlayFunctionListener ->
                mediaPlayFunctionListener.reset()
            }
        }
    }

    /**
     * 注册监听
     */
    fun addPlayFunctionListener(listener: MediaPlayFunctionListener) {
        if (!functionManage.contains(listener)) {
            functionManage.add(listener)
        }
    }

    /**
     * 移除监听
     */
    fun removePlayFunctionListener(listener: MediaPlayFunctionListener) {
        if (functionManage.contains(listener)) {
            functionManage.remove(listener)
        }
    }

    /**
     * 注册监听
     */
    fun addPlayInfoListener(listener: MediaPlayInfoListener) {
        if (!playInfoManage.contains(listener)) {
            playInfoManage.add(listener)
        }
    }

    /**
     * 移除监听
     */
    fun removePlayInfoListener(listener: MediaPlayInfoListener) {
        if (playInfoManage.contains(listener)) {
            playInfoManage.remove(listener)
        }
    }

    fun clearPlayInfoListener() {
        playInfoManage.clear()
    }

    fun clearPlayFunctionListener() {
        functionManage.clear()
    }

}

interface MediaPlayFunctionListener {
    //准备完成
    fun prepared()

    //开始播放
    fun start()

    // 暂停
    fun pause()

    //继续播放
    fun continuePlay()

    // 停止播放
    fun stop()

    //重置
    fun reset()
}

interface MediaPlayInfoListener {
    //播放错误监听
    fun onError(mp: MediaPlayer, what: Int, extra: Int)

    //播放完成监听
    fun onCompletion(mediaPlayer: MediaPlayer)

    //网络缓冲监听
    fun onBufferingUpdate(mediaPlayer: MediaPlayer, i: Int)

    //进度调整监听
    fun onSeekComplete(mediaPlayer: MediaPlayer)

    //时实播放进度
    fun onSeekBarProgress(progress: Int)
}